﻿// Copyright 2008 (c) Michael Reichenauer, SWEDEN. All rights reserved.
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PSMock.Implementation;

namespace PSMock
{
	/// <summary>
	/// Option for non typed functions mocks, i.e. the argument types have not been specified. 
	/// E.g.
	/// <code>
	/// Mock.Function(mocked.Echo(""))
	///   .Return("mocked");
	/// </code>
	/// </summary>
	public class FunctionOption : Option
	{
		public FunctionOption(MockedFunction mockedFunction)
			: base(mockedFunction)
		{ }

		/// <summary>
		/// Returns the specified return value for the mocked funktion.
		/// E.g.
		/// <code>
		/// Mock.Function(mocked.Echo(""))
		///   .Return("mocked");
		/// </code>
		/// </summary>
		/// <typeparam name="TResult">The type of the result.</typeparam>
		/// <param name="returnValue">The return value.</param>
		/// <returns></returns>
		public Option Return<TResult>(TResult returnValue)
		{
			mockedFunction.ReturnValue = returnValue;
			return this;
		}
	}



	/// <summary>
	/// Option for typed functions mocks, i.e. the return type has been specified. 
	/// E.g.
	/// <code>
	/// Mock.Function&lt;string&gt;(mocked.Echo))
	///   .Return("mocked");
	/// </code>
	/// </summary>
	/// <typeparam name="TResult">The type of the result.</typeparam>
	public class FunctionOption<TResult> : Option
	{
		public FunctionOption(MockedFunction mockedFunction) : base(mockedFunction) { }

		public FunctionOption<TResult> Condition(Func<bool> predicate)
		{
			mockedFunction.Condition = predicate;
			return this;
		}
		public FunctionOption<TResult> Return(TResult returnValue)
		{
			mockedFunction.ReturnValue = returnValue;
			return this;
		}
		public FunctionOption<TResult> Return(Func<TResult> function)
		{
			mockedFunction.Function = function;
			return this;
		}
	}

	/// <summary>
	/// Option for typed functions mocks, i.e. the return type and arguments have been specified. 
	/// E.g.
	/// <code>
	/// Mock.Function&lt;string, string&gt;(mocked.Echo))
	///   .Return("mocked");
	/// </code>
	/// </summary>
	/// <typeparam name="T1">The type of the argument.</typeparam>
	/// <typeparam name="TResult">The type of the result.</typeparam>
	public class FunctionMock<T1, TResult> : Option
	{
		public FunctionMock(MockedFunction mockedFunction) : base(mockedFunction) { }

		public FunctionMock(MockedFunction mockedFunction, TResult returnValue)
			: base(mockedFunction)
		{
			mockedFunction.ReturnValue = returnValue;
		}

		public FunctionMock<T1, TResult> Condition(Func<T1, bool> predicate)
		{
			mockedFunction.Condition = predicate;
			return this;
		}
		public FunctionMock<T1, TResult> Return(TResult returnValue)
		{
			mockedFunction.ReturnValue = returnValue;
			return this;
		}
		public FunctionMock<T1, TResult> Return(Func<T1, TResult> function)
		{
			mockedFunction.Function = function;
			return this;
		}
	}

	public class FunctionMock<T1, T2, TResult> : Option
	{
		public FunctionMock(MockedFunction mockedFunction) : base(mockedFunction) { }

		public FunctionMock(MockedFunction mockedFunction, TResult returnValue)
			: base(mockedFunction)
		{
			mockedFunction.ReturnValue = returnValue;
		}

		public FunctionMock<T1, T2, TResult> Condition(Func<T1, T2, bool> predicate)
		{
			mockedFunction.Condition = predicate;
			return this;
		}
		public FunctionMock<T1, T2, TResult> Return(TResult returnValue)
		{
			mockedFunction.ReturnValue = returnValue;
			return this;
		}
		public FunctionMock<T1, T2, TResult> Return(Func<T1, T2, TResult> function)
		{
			mockedFunction.Function = function;
			return this;
		}
	}

	public class FunctionMock<T1, T2, T3, TResult> : Option
	{
		public FunctionMock(MockedFunction mockedFunction) : base(mockedFunction) { }

		public FunctionMock(MockedFunction mockedFunction, TResult returnValue)
			: base(mockedFunction)
		{
			mockedFunction.ReturnValue = returnValue;
		}

		public FunctionMock<T1, T2, T3, TResult> Condition(Func<T1, T2, T3, bool> predicate)
		{
			mockedFunction.Condition = predicate;
			return this;
		}
		public FunctionMock<T1, T2, T3, TResult> Return(TResult returnValue)
		{
			mockedFunction.ReturnValue = returnValue;
			return this;
		}
		public FunctionMock<T1, T2, T3, TResult> Return(Func<T1, T2, T3, TResult> function)
		{
			mockedFunction.Function = function;
			return this;
		}
	}

	public class FunctionMock<T1, T2, T3, T4, TResult> : Option
	{
		public FunctionMock(MockedFunction mockedFunction) : base(mockedFunction) { }

		public FunctionMock(MockedFunction mockedFunction, TResult returnValue)
			: base(mockedFunction)
		{
			mockedFunction.ReturnValue = returnValue;
		}

		public FunctionMock<T1, T2, T3, T4, TResult> Condition(Func<T1, T2, T3, T4, bool> predicate)
		{
			mockedFunction.Condition = predicate;
			return this;
		}
		public FunctionMock<T1, T2, T3, T4, TResult> Return(TResult returnValue)
		{
			mockedFunction.ReturnValue = returnValue;
			return this;
		}
		public FunctionMock<T1, T2, T3, T4, TResult> Return(Func<T1, T2, T3, T4, TResult> function)
		{
			mockedFunction.Function = function;
			return this;
		}
	}
}
